package com.ziki.kwdj.window;

import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Date;
import java.util.EmptyStackException;

import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;

import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.log4j.xml.DOMConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ziki.common.util.PropertiesUtil;
import com.ziki.kwdj.biz.ViewClass;
import com.ziki.kwdj.model.ClassInfo;
import com.ziki.kwdj.model.Info;

public class MainFrame extends JFrame {
    private static Logger log = LoggerFactory.getLogger(MainFrame.class);
    private static final long serialVersionUID = 1L;
    private static final String CONFIG_FILE = "\\config\\setting.ini";
    private static final String LOG4J_FILE = "\\config\\log4j.xml";
    private static final String CONST_YYYYMMDDHHMISS = "yyyy/MM/dd HH:mm:ss";
    private ViewClass vc = new ViewClass();
    private JPanel contentPane;
    private JTextField txtName;
    private JTextField txtPwd;
    private JTextField txtCode;
    private JTextField txtClassName;
    private JTextField txtClassCnt;
    private JTextArea textArea;
    private JButton btnStart;
    private JButton btnStop;
    private JButton btnReloadImage;
    private JRadioButton rdMustLearn;
    private JRadioButton rdNeedLearn;
    private JRadioButton rdSelfLearn;
    private LearnThread thread;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    MainFrame frame = new MainFrame();
                    frame.setVisible(true);
                } catch (Exception e) {
                    log.error("Exception", e);
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public MainFrame() {
        setIconImage(Toolkit.getDefaultToolkit().getImage(MainFrame.class.getResource("/com/ziki/kwdj/icon/kwdj.jpg")));
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 580, 521);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        final JLabel lblName = new JLabel("用户名");
        lblName.setBounds(36, 10, 54, 15);
        contentPane.add(lblName);

        final JLabel lblPassword = new JLabel("密　码");
        lblPassword.setBounds(36, 35, 54, 15);
        contentPane.add(lblPassword);

        final JLabel lblCode = new JLabel("验证码");
        lblCode.setBounds(36, 60, 54, 15);
        contentPane.add(lblCode);

        txtName = new JTextField();
        txtName.setBounds(90, 7, 161, 21);
        contentPane.add(txtName);
        txtName.setColumns(10);

        txtPwd = new JTextField();
        txtPwd.setBounds(90, 32, 66, 21);
        contentPane.add(txtPwd);
        txtPwd.setColumns(10);

        txtCode = new JTextField();
        txtCode.setBounds(90, 57, 66, 21);
        contentPane.add(txtCode);
        txtCode.setColumns(10);

        final JButton btnLogin = new JButton("登录");
        btnLogin.setEnabled(false);
        btnLogin.setBounds(334, 6, 93, 23);
        contentPane.add(btnLogin);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setBounds(10, 181, 554, 302);
        scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        contentPane.add(scrollPane);

        textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setLineWrap(true);
        scrollPane.setViewportView(textArea);

        btnStart = new JButton("开始学习");
        btnStart.setBounds(334, 96, 93, 23);
        btnStart.setEnabled(false);
        contentPane.add(btnStart);

        btnStop = new JButton("停止学习");
        btnStop.setBounds(434, 96, 93, 23);
        btnStop.setEnabled(false);
        contentPane.add(btnStop);

        btnReloadImage = new JButton("重载验证码");
        btnReloadImage.setBounds(334, 52, 93, 23);
        contentPane.add(btnReloadImage);

        final JLabel lblImage = new JLabel();
        lblImage.setBounds(170, 48, 81, 30);
        contentPane.add(lblImage);

        rdMustLearn = new JRadioButton("必学");
        rdMustLearn.setSelected(true);
        rdMustLearn.setBounds(36, 96, 54, 23);
        contentPane.add(rdMustLearn);

        rdNeedLearn = new JRadioButton("选学");
        rdNeedLearn.setBounds(92, 96, 54, 23);
        contentPane.add(rdNeedLearn);

        rdSelfLearn = new JRadioButton("自学");
        rdSelfLearn.setBounds(148, 96, 54, 23);
        contentPane.add(rdSelfLearn);
        ButtonGroup group = new ButtonGroup();
        group.add(rdMustLearn);
        group.add(rdNeedLearn);
        group.add(rdSelfLearn);

        JButton btnLogout = new JButton("退出");
        btnLogout.setBounds(434, 6, 93, 23);
        contentPane.add(btnLogout);

        JLabel lblClassName = new JLabel("学习中课程：");
        lblClassName.setBounds(36, 153, 81, 15);
        contentPane.add(lblClassName);

        txtClassName = new JTextField();
        txtClassName.setEditable(false);
        txtClassName.setBounds(115, 150, 412, 21);
        contentPane.add(txtClassName);
        txtClassName.setColumns(10);

        JLabel lblClassCnt = new JLabel("本次学完数：");
        lblClassCnt.setBounds(36, 124, 81, 15);
        contentPane.add(lblClassCnt);

        txtClassCnt = new JTextField();
        txtClassCnt.setHorizontalAlignment(SwingConstants.RIGHT);
        txtClassCnt.setText("0");
        txtClassCnt.setEditable(false);
        txtClassCnt.setColumns(10);
        txtClassCnt.setBounds(115, 122, 81, 21);
        contentPane.add(txtClassCnt);

        // 截取空码
        txtName.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                String name = txtName.getText();
                if (StringUtils.isNotEmpty(name) && name.length() > 13) {
                    txtPwd.setText(name.substring(6, 14));
                }
            }
        });
        txtName.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                String name = txtName.getText();
                if (StringUtils.isNotEmpty(name) && name.length() > 13) {
                    txtPwd.setText(name.substring(6, 14));
                    if (StringUtils.isEmpty(txtCode.getText())) {
                        // 获取焦点
                        txtCode.dispatchEvent(new FocusEvent(txtCode, FocusEvent.FOCUS_GAINED, true));
                        txtCode.requestFocus();
                    }
                }
            }
        });

        // 登录
        btnLogin.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                new Thread() {
                    @Override
                    public void run() {
                        btnLogin.setEnabled(false);
                        Info info = new Info();
                        info.setUserName(txtName.getText());
                        info.setPassword(txtPwd.getText());
                        info.setCode(txtCode.getText());
                        if (StringUtils.isEmpty(info.getUserName())) {
                            textArea.append(outputLine("请输入用户名"));
                            return;
                        }
                        if (StringUtils.isEmpty(info.getPassword())) {
                            textArea.append(outputLine("请输入密码"));
                            return;
                        }
                        if (StringUtils.isEmpty(info.getCode())) {
                            textArea.append(outputLine("请输入验证码"));
                            return;
                        }
                        lblPassword.setVisible(false);
                        lblCode.setVisible(false);
                        txtName.setEnabled(false);
                        txtPwd.setVisible(false);
                        txtCode.setVisible(false);
                        lblImage.setVisible(false);
                        btnReloadImage.setVisible(false);

                        String msg = vc.login(info);
                        if ("0".equals(msg)) {
                            textArea.append(outputLine("登录成功"));
                            classOver();
                            // 保存用户
                            String configFile = System.getProperty("user.dir") + CONFIG_FILE;
                            PropertiesUtil prop = new PropertiesUtil(configFile);
                            String userName = prop.getProperty("username");
                            if (StringUtils.isEmpty(userName) || !userName.equals(txtName.getText())) {
                                prop.setProperty("username", txtName.getText());
                                prop.save();
                            }
                        } else {
                            lblPassword.setVisible(true);
                            lblCode.setVisible(true);
                            txtName.setEnabled(true);
                            txtPwd.setVisible(true);
                            txtCode.setVisible(true);
                            lblImage.setVisible(true);
                            btnReloadImage.setVisible(true);
                            btnStart.setEnabled(false);
                            btnLogin.setEnabled(true);
                            textArea.append(outputLine(msg));
                        }
                    }
                }.start();
            }
        });

        // 退出
        btnLogout.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (thread != null) {
                    thread.stopThread();
                }
                vc.logout();
                vc = new ViewClass();
                ImageIcon imgIcon = new ImageIcon(vc.getCodeNubImg());
                lblImage.setIcon(imgIcon);
                txtName.setText("");
                txtPwd.setText("");
                txtCode.setText("");
                txtClassCnt.setText("0");
                txtName.setEnabled(true);
                txtPwd.setVisible(true);
                txtCode.setVisible(true);
                lblPassword.setVisible(true);
                lblCode.setVisible(true);
                lblImage.setVisible(true);
                btnReloadImage.setVisible(true);
                textArea.append(outputLine("用户退出中……"));
                btnLogin.setEnabled(true);
                gotoEnd();
            }
        });

        // 课程开始
        btnStart.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                textArea.append(outputLine("课程开始"));
                thread = new LearnThread();
                thread.start();
                gotoEnd();
                rdMustLearn.setEnabled(false);
                rdNeedLearn.setEnabled(false);
                rdSelfLearn.setEnabled(false);
                btnStart.setEnabled(false);
                btnStop.setEnabled(true);
            }
        });

        // 课程停止
        btnStop.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (thread != null) {
                    thread.stopThread();
                }
                textArea.append(outputLine("课程学习停止……"));
                classOver();
                gotoEnd();
            }
        });

        // 验证码重新加载
        btnReloadImage.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                textArea.append(outputLine("验证码重新加载中……"));
                ImageIcon imgIcon = new ImageIcon(vc.getCodeNubImg());
                lblImage.setIcon(imgIcon);
                textArea.append(outputLine("验证码加载完毕，请登录"));
                gotoEnd();
            }
        });

        // 主线程初始化
        new Thread() {
            @Override
            public void run() {
                try {
                    String configFile = System.getProperty("user.dir") + CONFIG_FILE;
                    PropertiesUtil prop = new PropertiesUtil(configFile);
                    String userName = prop.getProperty("username");
                    if (StringUtils.isNotEmpty(userName)) {
                        txtName.setText(userName);
                        txtPwd.setText(userName.substring(6, 14));
                        // 获取焦点
                        txtCode.dispatchEvent(new FocusEvent(txtCode, FocusEvent.FOCUS_GAINED, true));
                        txtCode.requestFocus();
                    }
                    textArea.append(outputLine("验证码加载中……"));
                    ImageIcon imgIcon = new ImageIcon(vc.getCodeNubImg());
                    lblImage.setIcon(imgIcon);
                    btnLogin.setEnabled(true);
                    textArea.append(outputLine("验证码加载完毕，请登录"));
                    String logFilename = System.getProperty("user.dir") + LOG4J_FILE;
                    DOMConfigurator.configureAndWatch(logFilename);
                } catch (Exception e) {
                    log.error("Exception", e);
                }
            }
        }.start();
    }

    private String outputLine(String content) {
        StringBuffer sb = new StringBuffer();
        sb.append(DateFormatUtils.format(new Date(), CONST_YYYYMMDDHHMISS));
        sb.append("：");
        sb.append(content);
        sb.append("\n");
        return sb.toString();
    }

    /**
     * 本次学习课程学完课程统计
     */
    private void addClassCount() {
        // 本次学完课程+1
        int classCnt = NumberUtils.toInt(txtClassCnt.getText());
        txtClassCnt.setText(String.valueOf(classCnt + 1));
    }

    /**
     * 课程结束处理
     */
    private void classOver() {
        rdMustLearn.setEnabled(true);
        rdNeedLearn.setEnabled(true);
        rdSelfLearn.setEnabled(true);
        btnStart.setEnabled(true);
        btnStop.setEnabled(false);
    }

    private void gotoEnd() {
        // 滚动到末尾
        textArea.setCaretPosition(textArea.getText().length());
    }

    class LearnThread extends Thread {
        private Info learnInfo;
        private Info viewClassInfo;
        private ClassInfo classInfo;
        // 线程循环控制
        private boolean isRun = true;
        // 线程循环控制
        private boolean isWaiting = false;
        // 课程停止退出标志
        private boolean isOver = true;
        // 课程学习结束标志
        private boolean isClassEnd = false;
        // 课程类型
        private String classType = "1";
        // 错误次数
        private int errorCnt = 0;
        // 学习进度初始化
        int count = 1;

        public void run() {
            // 取得课程信息
            learnNextClass();
            // 学习中
            while (isRun) {
                if (isWaiting) {
                    try {
                        // 等待5秒钟
                        Thread.sleep(5000);
                        continue;
                    } catch (InterruptedException e) {
                    }
                }
                isOver = false;
                long start = System.currentTimeMillis();
                // 定时课程学习检测
                String content = "0";
                if (count % 5 == 0 || count >= classInfo.getClassMinute() - 1) {
                    viewClassInfo.setNowTime(count * 60 + RandomUtils.nextInt(1, 10));
                    content = vc.check(viewClassInfo);
                }
                // 检测结果
                if (StringUtils.isEmpty(content)) {
                    content = "学习课程《" + classInfo.getClassName() + "》时发生未知异常";
                }
                switch (content) {
                case "77":
                    content = "平台禁止同时观看多部视频教材。学习停止。";
                    isOver = true;
                    break;
                case "88":
                    content = "当前年度的此课程已学习完成。";
                    errorCnt++;
                    isClassEnd = true;
                    if (rdNeedLearn.isSelected()) {
                        rdSelfLearn.setSelected(true);
                    } else if (rdSelfLearn.isSelected()) {
                        rdMustLearn.setSelected(true);
                    } else {
                        rdNeedLearn.setSelected(true);
                    }
                    break;
                case "99":
                case "学分更新成功。积分转换成功。":
                    content = "恭喜您！当前课程已完成相关学习进度。";
                    // 本次学习课程统计
                    addClassCount();
                    isClassEnd = true;
                    break;
                case "0":
                    content = "正常进行中，学习进度(" + count + "/" + classInfo.getClassMinute() + ")";
                    errorCnt = 0;
                    break;
                default:
                    // 出现3次异常，结束本课程
                    if (errorCnt >= 2) {
                        isClassEnd = true;
                    }
                    errorCnt++;
                    content = "第" + errorCnt + "次错误:" + content;
                    log.error(content);
                    break;
                }
                // 输出结果
                textArea.append(outputLine(content));
                gotoEnd();
                // 课程异常结束
                if (isOver) {
                    textArea.append(outputLine("课程异常停止！"));
                    classOver();
                    return;
                }

                long end = System.currentTimeMillis();
                try {
                    if (end - start < 60000) {
                        // 定时检测等待时间
                        Thread.sleep(60000 - (end - start));
                    } else {
                        // 定时检测等待时间
                        Thread.sleep(57000);
                    }
                } catch (InterruptedException e) {
                }
                // 学习进度统计
                if (errorCnt == 0) {
                    count++;
                }
                // 课程结束
                if (isClassEnd) {
                    // 学习进度初始化
                    count = 1;
                    txtClassName.setText("准备学习下一课程");
                    textArea.append(outputLine("正在准备学习下一课程，请等待……"));
                    try {
                        // 下一课程等待2-5分钟
                        Thread.sleep(RandomUtils.nextLong(2, 5) * 60000L);
                    } catch (InterruptedException e) {
                    }
                    // 取得课程信息
                    if (isRun) {
                        learnNextClass();
                    }
                    isClassEnd = false;
                }
            }
            // 未学完处理
            if (!isClassEnd) {
                // 未学完的课程，重启加入队列
                learnInfo.getClassInfoStack().push(classInfo);
            }
            log.info("线程结束，课程《{}》学习停止！", classInfo.getClassName());
        }

        private void learnNextClass() {
            synchronized (rdNeedLearn) {

                // 1:必学 2:选学 3:自学
                if (rdNeedLearn.isSelected()) {
                    classType = "2";
                } else if (rdSelfLearn.isSelected()) {
                    classType = "3";
                } else {
                    classType = "1";
                }
                // 取得课程列表 信息
                learnInfo = vc.getClassInfoList(classType);
                if (learnInfo == null || learnInfo.getClassInfoStack() == null) {
                    textArea.append(outputLine("未知异常发生，课程列表取得失败，学习停止！"));
                    isRun = false;
                    isOver = true;
                    return;
                }
                try {
                    // 取得学习课程信息
                    classInfo = learnInfo.getClassInfoStack().pop();
                } catch (EmptyStackException e) {
                }
                if (classInfo == null) {
                    textArea.append(outputLine("未知异常发生，课程信息取得失败，学习停止！"));
                    isRun = false;
                    isOver = true;
                    return;
                }
                textArea.append(outputLine("开始学习课程：《" + classInfo.getClassName() + "》"));
                txtClassName.setText(classInfo.getClassName());
                try {
                    // 等待2-3秒钟
                    Thread.sleep(RandomUtils.nextLong(2000, 3000));
                } catch (InterruptedException e) {
                }
                // 模拟人操作，访问一个查看课程信息的中间页面
                vc.view(classInfo.getClassID());
                try {
                    // 等待2-4秒钟
                    Thread.sleep(RandomUtils.nextLong(2000, 4000));
                } catch (InterruptedException e) {
                }
                // 取得要学习课程的主要Key
                if (isRun) {
                    viewClassInfo = vc.getClassInfo(classInfo.getClassID());
                    // 取得上次看完的分钟
                    if (viewClassInfo.getCurrentClassMinutes() > 0) {
                        count = viewClassInfo.getCurrentClassMinutes() + 1;
                    }
                }
                while (StringUtils.isEmpty(viewClassInfo.getSessionID())) {
                    log.warn("viewClassInfo.getSessionID() == null!!");
                    try {
                        // 等待60-70秒钟
                        Thread.sleep(RandomUtils.nextLong(60000, 70000));
                    } catch (InterruptedException e) {
                    }
                    if (isRun) {
                        viewClassInfo = vc.getClassInfo(classInfo.getClassID());
                    }
                }

            }
        }

        public void stopThread() {
            isRun = false;
            isWaiting = false;
        }

        public void stopClass() {
            isWaiting = true;
        }
    }
}
